﻿using System;
using VsxFactory.Modeling.Strategies;
using VsxFactory.Modeling.VisualStudio;
using VsxFactory.Modeling.Repository;
using VsxFactory.Modeling.Strategies.VisualStudio;

namespace VsxFactory.Modeling.StrategyManager.Strategies
{
    internal class VisualStudioStrategyContext : StrategyContext
    {
        class WaitDialogWrapper : IProgressDialog
        {
            private WaitDialog _dlg;

            public WaitDialogWrapper(IServiceProvider serviceProvider, string title, string text) {
                _dlg = new WaitDialog(serviceProvider, title, text);
            }

            public void Update(string text, int value = 0) {
                _dlg.UpdateText(text);
            }

            public void Dispose() {
                _dlg.Dispose();
            }
        }

        private static readonly Guid strategyManagerOutputWindowGuid = new Guid("{4432371D-C10A-4A67-8D37-D8FB681DB0B2}");

        static IOutputWindow outputWindow;
        static VSErrorsListWindow errorsWindow;

        internal VisualStudioStrategyContext(IServiceProvider serviceProvider)
            : base(serviceProvider) {
            System.Diagnostics.Contracts.Contract.Requires(serviceProvider != null);
            Initialize();
        }

        protected override IStandardPackageRepository CreateLocalRepository() {
            return new LocalPackageRepository(this, PackageKind.Strategy);
        }

        protected override ReferencePackageRepository CreateSolutionRepository() {
            return new VisualStudioPackageRepository(this, PackageKind.Strategy);
        }

        private void Initialize() {
            if( outputWindow == null)
                outputWindow = new VsOutputWindow(ServiceProvider, strategyManagerOutputWindowGuid, "Strategy Manager");

            if (errorsWindow == null) {
                errorsWindow = new VSErrorsListWindow(ServiceProvider);
                errorsWindow.ClearErrors();
            }
        }

        public override IProgressDialog ShowProgressDialog(string title, string text) {
            return new WaitDialogWrapper(ServiceProvider, title, text);
        }

        /// <summary>
        /// Affichage d'un message dans le log
        /// </summary>
        /// <param name="format">Format du message</param>
        /// <param name="parms">Paramètres du format de message</param>
        public override void WriteLogMessage(string format, params object[] parms) {
            System.Diagnostics.Contracts.Contract.Requires(!String.IsNullOrWhiteSpace(format));
            outputWindow.Write(format, parms);
#if DEBUG
            System.Diagnostics.Debug.WriteLine("====> " + format, parms);
#endif
        }

        public override void ClearErrors() {
            errorsWindow.ClearErrors();
        }

        /// <summary>
        /// Affiche une erreur
        /// </summary>
        /// <param name="format">Format du message</param>
        /// <param name="parms">Paramètres du format de message</param>
        public override void WriteError(string format, params object[] parms) {
            System.Diagnostics.Contracts.Contract.Requires(!String.IsNullOrWhiteSpace(format));

            errorsWindow.WriteError(String.Format(format, parms), System.Diagnostics.EventLogEntryType.Error);
            WriteLogMessage("ERROR : " + format, parms);
        }

        public override bool PromptYesNo(string text) {
            return Utils.PromptYesNo(ServiceProvider, text);
        }

        private IStrategySettings settings;
        public override IStrategySettings Settings {
            get { return settings ?? (settings = new VisualStudioStrategySettings(ServiceProvider)); }
        }

        private IVsSolutionExplorer solutionExplorer;
        public override IVsSolutionExplorer SolutionExplorer {
            get { return solutionExplorer ?? (solutionExplorer = new VSSolutionExplorer(ServiceProvider)); }
        }

        public IProgressWindowOpener ProgressWindowOpener { get { return new ProgressWindowOpener(); } }
    }
}
